package com.gitee.wsl.compose.chart.sample

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.absolutePadding
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.unit.dp
import com.gitee.wsl.common.ui.draw.style.LineStyle
import com.gitee.wsl.compose.chart.ChartLayout
import com.gitee.wsl.compose.chart.ExperimentalKoalaPlotApi
import com.gitee.wsl.compose.chart.legend.LegendLocation
import com.gitee.wsl.compose.chart.xy.XYGraph
import com.gitee.wsl.compose.chart.xy.XYGraphScope
import com.gitee.wsl.compose.chart.xy.axis.model.IntLinearAxisModel
import com.gitee.wsl.compose.chart.xy.axis.model.LongLinearAxisModel
import com.gitee.wsl.compose.chart.xy.axis.style.rememberAxisStyle
import com.gitee.wsl.compose.chart.xy.line.LinePlot
import com.gitee.wsl.compose.chart.xy.model.PointEntry
import com.gitee.wsl.compose.modifier.layout.VerticalRotation
import com.gitee.wsl.compose.modifier.layout.rotateVertically

import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlin.random.Random

val timeLineSampleView = object : SampleView {
    override val name: String = "Time Chart"

    override val thumbnail = @Composable {
        ThumbnailTheme {
            TimeSamplePlot(true, name)
        }
    }

    override val content: @Composable () -> Unit = @Composable {
        TimeSamplePlot(false, "Random Walk")
    }
}

@OptIn(ExperimentalKoalaPlotApi::class)
@Composable
@Suppress("MagicNumber")
private fun TimeSamplePlot(thumbnail: Boolean, title: String) {
    val data = remember { mutableStateListOf(PointEntry(Clock.System.now().epochSeconds, 0)) }
    var yDataMin by remember { mutableStateOf(0) }
    var yDataMax by remember { mutableStateOf(1) }

    Column {
        if (!thumbnail) {
            Button(
                onClick = {
                    val yLast = data.last().y
                    val yNext = if (Random.nextBoolean()) {
                        yLast + 1
                    } else {
                        yLast - 1
                    }
                    data.add(PointEntry(Clock.System.now().epochSeconds, yNext))
                    yDataMin = minOf(yDataMin, yNext)
                    yDataMax = maxOf(yDataMax, yNext)
                }
            ) {
                Text("Add Step")
            }
        }

        ChartLayout(
            modifier = paddingMod.padding(end = 16.dp),
            title = { ChartTitle(title) },
            legendLocation = LegendLocation.BOTTOM
        ) {
            XYGraph(
                xAxisModel = LongLinearAxisModel(
                    range = (data.first().x)..(data.last().x) + 1
                ),
                yAxisModel = IntLinearAxisModel(
                    range = yDataMin..yDataMax
                ),
                xAxisLabels = {
                    if (!thumbnail) {
                        AxisLabel(Instant.fromEpochSeconds(it).toString(), Modifier.padding(top = 2.dp))
                    }
                },
                xAxisStyle = rememberAxisStyle(labelRotation = 90),
                xAxisTitle = {
                    if (!thumbnail) {
                        Box(
                            modifier = Modifier.fillMaxWidth(),
                            contentAlignment = Alignment.Center
                        ) {
                            AxisTitle("Time")
                        }
                    }
                },
                yAxisLabels = {
                    if (!thumbnail) AxisLabel(it.toString(), Modifier.absolutePadding(right = 2.dp))
                },
                yAxisTitle = {
                    if (!thumbnail) {
                        Box(
                            modifier = Modifier.fillMaxHeight(),
                            contentAlignment = Alignment.TopStart
                        ) {
                            AxisTitle(
                                "Value",
                                modifier = Modifier.rotateVertically(VerticalRotation.COUNTER_CLOCKWISE)
                                    .padding(bottom = padding)
                            )
                        }
                    }
                }
            ) {
                chart(data)
            }
        }
    }
}

@OptIn(ExperimentalKoalaPlotApi::class)
@Composable
private fun XYGraphScope<Long, Int>.chart(data: List<PointEntry<Long, Int>>) {
    LinePlot(
        data = data,
        lineStyle = LineStyle(
            brush = SolidColor(Color.Black),
            strokeWidth = 2.dp
        ),
    )
}
